#include "udp_multicast.h"

#include <strings.h>
#include <arpa/inet.h>
#include <sys/sysinfo.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <google/protobuf/message.h>
#include <boost/filesystem.hpp>
#include <netinet/in.h>
#include <openssl/hmac.h>
#include <netinet/ip.h>

#include "hmac.h"


//#define MULTICASTIP "224.0.0.1"
//#define CLIENT_MULTICASTPORT 3232
#define BLOB_SIZE 1000

#define MAXBUFSIZE 65536 // Max UDP Packet size is 64 Kbyte

// char buffer[MAXBUFSIZE];


	udp_multicast::udp_multicast(std::string const& multicastip, int port, std::string const& interface) 
	{

   unsigned char ttl = 3;
   unsigned char one = 1;

   memset(&saddr, 0, sizeof(struct sockaddr_in));
   memset(&iaddr, 0, sizeof(struct in_addr));

   sock = socket(PF_INET, SOCK_DGRAM, 0);
   if ( sock < 0 )
     perror("Error creating socket"), exit(0);

   saddr.sin_family = PF_INET;
   saddr.sin_port = htons(0); // Use the first free port
   saddr.sin_addr.s_addr = inet_addr(interface.c_str()); // bind socket to any interface
   status = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));

   if ( status < 0 )
     perror("Error binding socket to interface"), exit(0);

   iaddr.s_addr = INADDR_ANY; // use DEFAULT interface

   setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &iaddr, sizeof(struct in_addr));

//   setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
//	      sizeof(unsigned char));

   status = setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
		       &one, sizeof(unsigned char));

   saddr.sin_family = PF_INET;
   saddr.sin_addr.s_addr = inet_addr(multicastip.c_str());
   saddr.sin_port = htons(port);

//   strcpy(buffer, "Hello world\n");

   socklen = sizeof(struct sockaddr_in);
	}

	udp_multicast::~udp_multicast()
	{
   		// shutdown socket
   		shutdown(sock, 2);
   		// close socket
   		close(sock);

	} 

	void udp_multicast::send(server::Block const& block) 
	{
//		pthread_mutex_lock(&m_lock);
		std::string data;
		block.SerializeToString(&data);
		data.append(hmac(data));
		sendto(sock,data.c_str(),data.size(),0,
		       (struct sockaddr *)&saddr,sizeof(saddr));
//		usleep(10000);

//		pthread_mutex_unlock(&m_lock);
	}

/*
udp_multicast sender(CLIENT_MULTICASTPORT);




void* heartbeatSendThread(void *arg) {
        while(1) {

                server::Block block;
                unsigned int t = static_cast<unsigned int>(time(NULL));
                block.mutable_master()->set_time(t);

                sender.send(block);
                sleep(1);
        }
        return NULL;
}




int main(int argc, char**argv) 
{


	srand (time(NULL));


		pthread_t heartbeatProcess;
		pthread_create(&(heartbeatProcess), NULL, &heartbeatSendThread, NULL);


		pthread_join(heartbeatProcess, NULL);


	return 0;
}
*/
